package com.gzs.learn.admin.config;

import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonGenerator.Feature;
import com.fasterxml.jackson.core.json.JsonReadFeature;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import javax.annotation.PostConstruct;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * @author zhisong.guan
 */
@Configuration
@RequiredArgsConstructor
@Slf4j
public class WebMvcConfig {
    @Value("${global.local-date-time-fmt:yyyy-MM-dd'T'HH:mm:ss}")
    private String dateTimePattern;
    @Value("${global.local-date-fmt:yyyy-MM-dd}")
    private String datePattern;
    private final MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter;

    /**
     * 序列化json时,将所有的long变成string 因为js中得数字类型不能包含所有的java long值
     */
    @PostConstruct
    public void configureMessageConverters() {
        ObjectMapper objectMapper = mappingJackson2HttpMessageConverter.getObjectMapper();
        SimpleModule longModule = new SimpleModule("long-module");
        longModule.addSerializer(Long.class, ToStringSerializer.instance);
        longModule.addSerializer(Long.TYPE, ToStringSerializer.instance);
        objectMapper.registerModule(longModule);

        DateTimeFormatter dateTimeFmt = DateTimeFormatter.ofPattern(dateTimePattern);
        SimpleModule dateTimeModule = new SimpleModule();
        dateTimeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer(dateTimeFmt));
        dateTimeModule.addDeserializer(LocalDateTime.class, new LocalDateTimeDeserializer(dateTimeFmt));
        objectMapper.registerModule(dateTimeModule);

        DateTimeFormatter dateFmt = DateTimeFormatter.ofPattern(datePattern);
        SimpleModule dateModule = new SimpleModule();
        dateModule.addSerializer(LocalDate.class, new LocalDateSerializer(dateFmt));
        dateModule.addDeserializer(LocalDate.class, new LocalDateDeserializer(dateFmt));
        objectMapper.registerModule(dateModule);

        ////////////////////////////////////
        // 启用的特性列表
        ////////////////////////////////////
        // decimal输出为字符串
        objectMapper.enable(Feature.WRITE_BIGDECIMAL_AS_PLAIN);
        // 是否允许带反斜杠字符
        objectMapper.enable(JsonReadFeature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER.mappedFeature());
        // 是否允许注释
        objectMapper.enable(JsonReadFeature.ALLOW_JAVA_COMMENTS.mappedFeature());
        // 是否允许解析前导0
        objectMapper.enable(JsonReadFeature.ALLOW_LEADING_ZEROS_FOR_NUMBERS.mappedFeature());

        ////////////////////////////////////
        // 禁用用的特性列表
        ////////////////////////////////////
        // 空兑现不抛出异常
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        // 未知字段解析是否抛出异常,false 不抛出解析异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 忽略的属性不抛出异常
        objectMapper.disable(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES);

        // null属性的字段不输出
        objectMapper.setSerializationInclusion(Include.NON_NULL);
        log.info("global date fmt pattern {},datetime fmt {}", datePattern, dateTimePattern);
    }
}
